
typedef struct errorcode_to_id {
	unsigned int error;
	const char*  id;
} errorcode_to_id_t;

typedef struct error_id_to_message {
	const char* id;
	const char* message;
} error_id_to_message_t;

// Parts of error code to localization id map is taken from SDMMobileDevice framework. Associated license is bellow.
// https://github.com/samdmarshall/SDMMobileDevice/blob/master/Framework/MobileDevice/Error/SDMMD_Error.h
//
// Copyright (c) 2014, Sam Marshall
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 
// 		in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of Sam Marshall nor the names of its contributors may be used to endorse or promote products derived from this
// 		software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static errorcode_to_id_t errorcode_to_id[] = {
	{ 0x00000000, "kAMDSuccess" },
	{ 0xe8000001, "kAMDUndefinedError" },
	{ 0xe8000002, "kAMDBadHeaderError" },
	{ 0xe8000003, "kAMDNoResourcesError" },
	{ 0xe8000004, "kAMDReadError" },
	{ 0xe8000005, "kAMDWriteError" },
	{ 0xe8000006, "kAMDUnknownPacketError" },
	{ 0xe8000007, "kAMDInvalidArgumentError" },
	{ 0xe8000008, "kAMDNotFoundError" },
	{ 0xe8000009, "kAMDIsDirectoryError" },
	{ 0xe800000a, "kAMDPermissionError" },
	{ 0xe800000b, "kAMDNotConnectedError" },
	{ 0xe800000c, "kAMDTimeOutError" },
	{ 0xe800000d, "kAMDOverrunError" },
	{ 0xe800000e, "kAMDEOFError" },
	{ 0xe800000f, "kAMDUnsupportedError" },
	{ 0xe8000010, "kAMDFileExistsError" },
	{ 0xe8000011, "kAMDBusyError" },
	{ 0xe8000012, "kAMDCryptoError" },
	{ 0xe8000013, "kAMDInvalidResponseError" },
	{ 0xe8000014, "kAMDMissingKeyError" },
	{ 0xe8000015, "kAMDMissingValueError" },
	{ 0xe8000016, "kAMDGetProhibitedError" },
	{ 0xe8000017, "kAMDSetProhibitedError" },
	{ 0xe8000018, "kAMDRemoveProhibitedError" },
	{ 0xe8000019, "kAMDImmutableValueError" },
	{ 0xe800001a, "kAMDPasswordProtectedError" },
	{ 0xe800001b, "kAMDMissingHostIDError" },
	{ 0xe800001c, "kAMDInvalidHostIDError" },
	{ 0xe800001d, "kAMDSessionActiveError" },
	{ 0xe800001e, "kAMDSessionInactiveError" },
	{ 0xe800001f, "kAMDMissingSessionIDError" },
	{ 0xe8000020, "kAMDInvalidSessionIDError" },
	{ 0xe8000021, "kAMDMissingServiceError" },
	{ 0xe8000022, "kAMDInvalidServiceError" },
	{ 0xe8000023, "kAMDInvalidCheckinError" },
	{ 0xe8000024, "kAMDCheckinTimeoutError" },
	{ 0xe8000025, "kAMDMissingPairRecordError" },
	{ 0xe8000026, "kAMDInvalidActivationRecordError" },
	{ 0xe8000027, "kAMDMissingActivationRecordError" },
	{ 0xe8000028, "kAMDWrongDroidError" },
	{ 0xe8000029, "kAMDSUVerificationError" },
	{ 0xe800002a, "kAMDSUPatchError" },
	{ 0xe800002b, "kAMDSUFirmwareError" },
	{ 0xe800002c, "kAMDProvisioningProfileNotValid" },
	{ 0xe800002d, "kAMDSendMessageError" },
	{ 0xe800002e, "kAMDReceiveMessageError" },
	{ 0xe800002f, "kAMDMissingOptionsError" },
	{ 0xe8000030, "kAMDMissingImageTypeError" },
	{ 0xe8000031, "kAMDDigestFailedError" },
	{ 0xe8000032, "kAMDStartServiceError" },
	{ 0xe8000033, "kAMDInvalidDiskImageError" },
	{ 0xe8000034, "kAMDMissingDigestError" },
	{ 0xe8000035, "kAMDMuxError" },
	{ 0xe8000036, "kAMDApplicationAlreadyInstalledError" },
	{ 0xe8000037, "kAMDApplicationMoveFailedError" },
	{ 0xe8000038, "kAMDApplicationSINFCaptureFailedError" },
	{ 0xe8000039, "kAMDApplicationSandboxFailedError" },
	{ 0xe800003a, "kAMDApplicationVerificationFailedError" },
	{ 0xe800003b, "kAMDArchiveDestructionFailedError" },
	{ 0xe800003c, "kAMDBundleVerificationFailedError" },
	{ 0xe800003d, "kAMDCarrierBundleCopyFailedError" },
	{ 0xe800003e, "kAMDCarrierBundleDirectoryCreationFailedError" },
	{ 0xe800003f, "kAMDCarrierBundleMissingSupportedSIMsError" },
	{ 0xe8000040, "kAMDCommCenterNotificationFailedError" },
	{ 0xe8000041, "kAMDContainerCreationFailedError" },
	{ 0xe8000042, "kAMDContainerP0wnFailedError" },
	{ 0xe8000043, "kAMDContainerRemovalFailedError" },
	{ 0xe8000044, "kAMDEmbeddedProfileInstallFailedError" },
	{ 0xe8000045, "kAMDErrorError" },
	{ 0xe8000046, "kAMDExecutableTwiddleFailedError" },
	{ 0xe8000047, "kAMDExistenceCheckFailedError" },
	{ 0xe8000048, "kAMDInstallMapUpdateFailedError" },
	{ 0xe8000049, "kAMDManifestCaptureFailedError" },
	{ 0xe800004a, "kAMDMapGenerationFailedError" },
	{ 0xe800004b, "kAMDMissingBundleExecutableError" },
	{ 0xe800004c, "kAMDMissingBundleIdentifierError" },
	{ 0xe800004d, "kAMDMissingBundlePathError" },
	{ 0xe800004e, "kAMDMissingContainerError" },
	{ 0xe800004f, "kAMDNotificationFailedError" },
	{ 0xe8000050, "kAMDPackageExtractionFailedError" },
	{ 0xe8000051, "kAMDPackageInspectionFailedError" },
	{ 0xe8000052, "kAMDPackageMoveFailedError" },
	{ 0xe8000053, "kAMDPathConversionFailedError" },
	{ 0xe8000054, "kAMDRestoreContainerFailedError" },
	{ 0xe8000055, "kAMDSeatbeltProfileRemovalFailedError" },
	{ 0xe8000056, "kAMDStageCreationFailedError" },
	{ 0xe8000057, "kAMDSymlinkFailedError" },
	{ 0xe8000058, "kAMDiTunesArtworkCaptureFailedError" },
	{ 0xe8000059, "kAMDiTunesMetadataCaptureFailedError" },
	{ 0xe800005a, "kAMDAlreadyArchivedError" },
	{ 0xe800005b, "kAMDServiceLimitError" },
	{ 0xe800005c, "kAMDInvalidPairRecordError" },
	{ 0xe800005d, "kAMDServiceProhibitedError" },
	{ 0xe800005e, "kAMDCheckinSetupFailedError" },
	{ 0xe800005f, "kAMDCheckinConnectionFailedError" },
	{ 0xe8000060, "kAMDCheckinReceiveFailedError" },
	{ 0xe8000061, "kAMDCheckinResponseFailedError" },
	{ 0xe8000062, "kAMDCheckinSendFailedError" },
	{ 0xe8000063, "kAMDMuxCreateListenerError" },
	{ 0xe8000064, "kAMDMuxGetListenerError" },
	{ 0xe8000065, "kAMDMuxConnectError" },
	{ 0xe8000066, "kAMDUnknownCommandError" },
	{ 0xe8000067, "kAMDAPIInternalError" },
	{ 0xe8000068, "kAMDSavePairRecordFailedError" },
	{ 0xe8000069, "kAMDCheckinOutOfMemoryError" },
	{ 0xe800006a, "kAMDDeviceTooNewError" },
	{ 0xe800006b, "kAMDDeviceRefNoGood" },
	{ 0xe800006c, "kAMDCannotTranslateError" },
	{ 0xe800006d, "kAMDMobileImageMounterMissingImageSignature" },
	{ 0xe800006e, "kAMDMobileImageMounterResponseCreationFailed" },
	{ 0xe800006f, "kAMDMobileImageMounterMissingImageType" },
	{ 0xe8000070, "kAMDMobileImageMounterMissingImagePath" },
	{ 0xe8000071, "kAMDMobileImageMounterImageMapLoadFailed" },
	{ 0xe8000072, "kAMDMobileImageMounterAlreadyMounted" },
	{ 0xe8000073, "kAMDMobileImageMounterImageMoveFailed" },
	{ 0xe8000074, "kAMDMobileImageMounterMountPathMissing" },
	{ 0xe8000075, "kAMDMobileImageMounterMountPathNotEmpty" },
	{ 0xe8000076, "kAMDMobileImageMounterImageMountFailed" },
	{ 0xe8000077, "kAMDMobileImageMounterTrustCacheLoadFailed" },
	{ 0xe8000078, "kAMDMobileImageMounterDigestFailed" },
	{ 0xe8000079, "kAMDMobileImageMounterDigestCreationFailed" },
	{ 0xe800007a, "kAMDMobileImageMounterImageVerificationFailed" },
	{ 0xe800007b, "kAMDMobileImageMounterImageInfoCreationFailed" },
	{ 0xe800007c, "kAMDMobileImageMounterImageMapStoreFailed" },
	{ 0xe800007d, "kAMDBonjourSetupError" },
	{ 0xe800007e, "kAMDDeviceOSVersionTooLow" },
	{ 0xe800007f, "kAMDNoWifiSyncSupportError" },
	{ 0xe8000080, "kAMDDeviceFamilyNotSupported" },
	{ 0xe8000081, "kAMDEscrowLockedError" },
	{ 0xe8000082, "kAMDPairingProhibitedError" },
	{ 0xe8000083, "kAMDProhibitedBySupervision" },
	{ 0xe8000084, "kAMDDeviceDisconnectedError" },
	{ 0xe8000085, "kAMDTooBigError" },
	{ 0xe8000086, "kAMDPackagePatchFailedError" },
	{ 0xe8000087, "kAMDIncorrectArchitectureError" },
	{ 0xe8000088, "kAMDPluginCopyFailedError" },
	{ 0xe8000089, "kAMDBreadcrumbFailedError" },
	{ 0xe800008a, "kAMDBreadcrumbUnlockError" },
	{ 0xe800008b, "kAMDGeoJSONCaptureFailedError" },
	{ 0xe800008c, "kAMDNewsstandArtworkCaptureFailedError" },
	{ 0xe800008d, "kAMDMissingCommandError" },
	{ 0xe800008e, "kAMDNotEntitledError" },
	{ 0xe800008f, "kAMDMissingPackagePathError" },
	{ 0xe8000090, "kAMDMissingContainerPathError" },
	{ 0xe8000091, "kAMDMissingApplicationIdentifierError" },
	{ 0xe8000092, "kAMDMissingAttributeValueError" },
	{ 0xe8000093, "kAMDLookupFailedError" },
	{ 0xe8000094, "kAMDDictCreationFailedError" },
	{ 0xe8000095, "kAMDUserDeniedPairingError" },
	{ 0xe8000096, "kAMDPairingDialogResponsePendingError" },
	{ 0xe8000097, "kAMDInstallProhibitedError" },
	{ 0xe8000098, "kAMDUninstallProhibitedError" },
	{ 0xe8000099, "kAMDFMiPProtectedError" },
	{ 0xe800009a, "kAMDMCProtected" },
	{ 0xe800009b, "kAMDMCChallengeRequired" },
	{ 0xe800009c, "kAMDMissingBundleVersionError" },
	{ 0xe800009d, "kAMDAppBlacklistedError" },
	{ 0xe800009e, "This app contains an app extension with an illegal bundle identifier. App extension bundle identifiers must have a prefix consisting of their containing application's bundle identifier followed by a '.'." },
	{ 0xe800009f, "If an app extension defines the XPCService key in its Info.plist, it must have a dictionary value." },
	{ 0xe80000a0, "App extensions must define the NSExtension key with a dictionary value in their Info.plist." },
	{ 0xe80000a1, "If an app extension defines the CFBundlePackageType key in its Info.plist, it must have the value \"XPC!\"." },
	{ 0xe80000a2, "App extensions must define either NSExtensionMainStoryboard or NSExtensionPrincipalClass keys in the NSExtension dictionary in their Info.plist." },
	{ 0xe80000a3, "If an app extension defines the NSExtensionContextClass key in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters." },
	{ 0xe80000a4, "If an app extension defines the NSExtensionContextHostClass key in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters." },
	{ 0xe80000a5, "If an app extension defines the NSExtensionViewControllerHostClass key in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters." },
	{ 0xe80000a6, "This app contains an app extension that does not define the NSExtensionPointIdentifier key in its Info.plist. This key must have a reverse-DNS format string value." },
	{ 0xe80000a7, "This app contains an app extension that does not define the NSExtensionPointIdentifier key in its Info.plist with a valid reverse-DNS format string value." },
	{ 0xe80000a8, "If an app extension defines the NSExtensionAttributes key in the NSExtension dictionary in its Info.plist, it must have a dictionary value." },
	{ 0xe80000a9, "If an app extension defines the NSExtensionPointName key in the NSExtensionAttributes dictionary in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters." },
	{ 0xe80000aa, "If an app extension defines the NSExtensionPointVersion key in the NSExtensionAttributes dictionary in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters." },
	{ 0xe80000ab, "This app or a bundle it contains does not define the CFBundleName key in its Info.plist with a string value containing one or more characters." },
	{ 0xe80000ac, "This app or a bundle it contains does not define the CFBundleDisplayName key in its Info.plist with a string value containing one or more characters." },
	{ 0xe80000ad, "This app or a bundle it contains defines the CFBundleShortVersionStringKey key in its Info.plist with a non-string value or a zero-length string value." },
	{ 0xe80000ae, "This app or a bundle it contains defines the RunLoopType key in the XPCService dictionary in its Info.plist with a non-string value or a zero-length string value." },
	{ 0xe80000af, "This app or a bundle it contains defines the ServiceType key in the XPCService dictionary in its Info.plist with a non-string value or a zero-length string value." },
	{ 0xe80000b0, "This application or a bundle it contains has the same bundle identifier as this application or another bundle that it contains. Bundle identifiers must be unique." },
	{ 0xe80000b1, "This app contains an app extension that specifies an extension point identifier that is not supported on this version of iOS for the value of the NSExtensionPointIdentifier key in its Info.plist." },
	{ 0xe80000b2, "This app contains multiple app extensions that are file providers. Apps are only allowed to contain at most a single file provider app extension." },
	{ 0xe80000b3, "kMobileHouseArrestMissingCommand" },
	{ 0xe80000b4, "kMobileHouseArrestUnknownCommand" },
	{ 0xe80000b5, "kMobileHouseArrestMissingIdentifier" },
	{ 0xe80000b6, "kMobileHouseArrestDictionaryFailed" },
	{ 0xe80000b7, "kMobileHouseArrestInstallationLookupFailed" },
	{ 0xe80000b8, "kMobileHouseArrestApplicationLookupFailed" },
	{ 0xe80000b9, "kMobileHouseArrestMissingContainer" },
	// 0xe80000ba does not exist
	{ 0xe80000bb, "kMobileHouseArrestPathConversionFailed" },
	{ 0xe80000bc, "kMobileHouseArrestPathMissing" },
	{ 0xe80000bd, "kMobileHouseArrestInvalidPath" },
	{ 0xe80000be, "kAMDMismatchedApplicationIdentifierEntitlementError" },
	{ 0xe80000bf, "kAMDInvalidSymlinkError" },
	{ 0xe80000c0, "kAMDNoSpaceError" },
	{ 0xe80000c1, "The WatchKit app extension must have, in its Info.plist's NSExtension dictionary's NSExtensionAttributes dictionary, the key WKAppBundleIdentifier with a value equal to the associated WatchKit app's bundle identifier." },
	{ 0xe80000c2, "This app is not a valid AppleTV Stub App" },
	{ 0xe80000c3, "kAMDBundleiTunesMetadataVersionMismatchError" },
	{ 0xe80000c4, "kAMDInvalidiTunesMetadataPlistError" },
	{ 0xe80000c5, "kAMDMismatchedBundleIDSigningIdentifierError" },
	{ 0xe80000c6, "This app contains multiple WatchKit app extensions. Only a single WatchKit extension is allowed." },
	{ 0xe80000c7, "A WatchKit app within this app is not a valid bundle." },
	{ 0xe80000c8, "kAMDDeviceNotSupportedByThinningError" },
	{ 0xe80000c9, "The UISupportedDevices key in this app's Info.plist does not specify a valid set of supported devices." },
	{ 0xe80000ca, "This app contains an app extension with an illegal bundle identifier. App extension bundle identifiers must have a prefix consisting of their containing application's bundle identifier followed by a '.', with no further '.' characters after the prefix." },
	{ 0xe80000cb, "kAMDAppexBundleIDConflictWithOtherIdentifierError" },
	{ 0xe80000cc, "kAMDBundleIDConflictWithOtherIdentifierError" },
	{ 0xe80000cd, "This app contains multiple WatchKit 1.0 apps. Only a single WatchKit 1.0 app is allowed." },
	{ 0xe80000ce, "This app contains multiple WatchKit 2.0 apps. Only a single WatchKit 2.0 app is allowed." },
	{ 0xe80000cf, "The WatchKit app has an invalid stub executable." },
	{ 0xe80000d0, "The WatchKit app has multiple app extensions. Only a single WatchKit extension is allowed in a WatchKit app, and only if this is a WatchKit 2.0 app." },
	{ 0xe80000d1, "The WatchKit 2.0 app contains non-WatchKit app extensions. Only WatchKit app extensions are allowed in WatchKit apps." },
	{ 0xe80000d2, "The WatchKit app has one or more embedded frameworks. Frameworks are only allowed in WatchKit app extensions in WatchKit 2.0 apps." },
	{ 0xe80000d3, "This app contains a WatchKit 1.0 app with app extensions. This is not allowed." },
	{ 0xe80000d4, "This app contains a WatchKit 2.0 app without an app extension. WatchKit 2.0 apps must contain a WatchKit app extension." },
	{ 0xe80000d5, "The WatchKit app's Info.plist must have a WKCompanionAppBundleIdentifier key set to the bundle identifier of the companion app." },
	{ 0xe80000d6, "The WatchKit app's Info.plist contains a non-string key." },
	{ 0xe80000d7, "The WatchKit app's Info.plist contains a key that is not in the whitelist of allowed keys for a WatchKit app." },
	{ 0xe80000d8, "The WatchKit 1.0 and a WatchKit 2.0 apps within this app must have have the same bundle identifier." },
	{ 0xe80000d9, "This app contains a WatchKit app with an invalid bundle identifier. The bundle identifier of a WatchKit app must have a prefix consisting of the companion app's bundle identifier, followed by a '.'." },
	{ 0xe80000da, "This app contains a WatchKit app where the UIDeviceFamily key in its Info.plist does not specify the value 4 to indicate that it's compatible with the Apple Watch device type." },
	{ 0xe80000db, "The device is out of storage for apps. Please remove some apps from the device and try again." },
	{ 0xe80000dc, "This app or an app that it contains has a Siri Intents app extension that is missing the IntentsSupported array in the NSExtensionAttributes dictionary in the NSExtension dictionary in its Info.plist." },
	{ 0xe80000dd, "This app or an app that it contains has a Siri Intents app extension that does not correctly define the IntentsRestrictedWhileLocked key in the NSExtensionAttributes dictionary in the NSExtension dictionary in its Info.plist. The key's value must be an array of strings." },
	{ 0xe80000de, "This app or an app that it contains has a Siri Intents app extension that declares values in its IntentsRestrictedWhileLocked key's array value that are not in its IntentsSupported key's array value (in the NSExtensionAttributes dictionary in the NSExtension dictionary in its Info.plist)." },
	{ 0xe80000df, "This app or an app that it contains declares multiple Siri Intents app extensions that declare one or more of the same values in the IntentsSupported array in the NSExtensionAttributes dictionary in the NSExtension dictionary in their Info.plist. IntentsSupported must be distinct among a given Siri Intents extension type within an app." },
	{ 0xe80000e0, "The WatchKit 2.0 app, which expects to be compatible with watchOS versions earlier than 3.0, contains a non-WatchKit extension in a location that's not compatible with watchOS versions earlier than 3.0." },
	{ 0xe80000e1, "The WatchKit 2.0 app, which expects to be compatible with watchOS versions earlier than 3.0, contains a framework in a location that's not compatible with watchOS versions earlier than 3.0." },
	{ 0xe80000e2, "kAMDMobileImageMounterDeviceLocked" },
	{ 0xe80000e3, "kAMDInvalidSINFError" },
	{ 0xe80000e4, "Multiple iMessage app extensions were found in this app. Only one is allowed." },
	{ 0xe80000e5, "This iMessage application is missing its required iMessage app extension." },
	{ 0xe80000e6, "This iMessage application contains an app extension type other than an iMessage app extension. iMessage applications may only contain one iMessage app extension and may not contain other types of app extensions." },
	{ 0xe80000e7, "This app contains a WatchKit app with one or more Siri Intents app extensions that declare IntentsSupported that are not declared in any of the companion app's Siri Intents app extensions. WatchKit Siri Intents extensions' IntentsSupported values must be a subset of the companion app's Siri Intents extensions' IntentsSupported values." },
	{ 0xe80000e8, "kAMDRequireCUPairingCodeError" },
	{ 0xe80000e9, "kAMDRequireCUPairingBackoffError" },
	{ 0xe80000ea, "kAMDCUPairingError" },
	{ 0xe80000eb, "kAMDCUPairingContinueError" },
	{ 0xe80000ec, "kAMDCUPairingResetError" },
	{ 0xe80000ed, "kAMDRequireCUPairingError" },
	{ 0xe80000ee, "kAMDPasswordRequiredError" },

	// Errors without id->string mapping.
	{ 0xe8008001, "An unknown error has occurred." },
	{ 0xe8008002, "Attempted to modify an immutable provisioning profile." },
	{ 0xe8008003, "This provisioning profile is malformed." },
	{ 0xe8008004, "This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature)." },
	{ 0xe8008005, "This provisioning profile is malformed." },
	{ 0xe8008006, "This provisioning profile is malformed." },
	{ 0xe8008007, "This provisioning profile is malformed." },
	{ 0xe8008008, "This provisioning profile is malformed." },
	{ 0xe8008009, "The signature was not valid." },
	{ 0xe800800a, "Unable to allocate memory." },
	{ 0xe800800b, "A file operation failed." },
	{ 0xe800800c, "There was an error communicating with your device." },
	{ 0xe800800d, "There was an error communicating with your device." },
	{ 0xe800800e, "This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature)." },
	{ 0xe800800f, "The application's signature is valid but it does not match the expected hash." },
	{ 0xe8008010, "This provisioning profile is unsupported." },
	{ 0xe8008011, "This provisioning profile has expired." },
	{ 0xe8008012, "This provisioning profile cannot be installed on this device." },
	{ 0xe8008013, "This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature)." },
	{ 0xe8008014, "The executable contains an invalid signature." },
	{ 0xe8008015, "A valid provisioning profile for this executable was not found." },
	{ 0xe8008016, "The executable was signed with invalid entitlements." },
	{ 0xe8008017, "A signed resource has been added, modified, or deleted." },
	{ 0xe8008018, "The identity used to sign the executable is no longer valid." },
	{ 0xe8008019, "The application does not have a valid signature." },
	{ 0xe800801a, "This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature)." },
	{ 0xe800801b, "There was an error communicating with your device." },
	{ 0xe800801c, "No code signature found." },
	{ 0xe800801d, "Rejected by policy." },
	{ 0xe800801e, "The requested profile does not exist (it may have been removed)." },
	{ 0xe800801f, "Attempted to install a Beta profile without the proper entitlement." },
	{ 0xe8008020, "Attempted to install a Beta profile over lockdown connection." },
	{ 0xe8008021, "The maximum number of apps for free development profiles has been reached." },
	{ 0xe8008022, "An error occured while accessing the profile database." },
	{ 0xe8008023, "An error occured while communicating with the agent." },
	{ 0xe8008024, "The provisioning profile is banned." },
	{ 0xe8008025, "The user did not explicitly trust the provisioning profile." },
	{ 0xe8008026, "The provisioning profile requires online authorization." },
	{ 0xe8008027, "The cdhash is not in the trust cache." },
	{ 0xe8008028, "Invalid arguments or option combination." },
};

const int errorcode_to_id_count = sizeof(errorcode_to_id) / sizeof(errorcode_to_id_t);

// Taken from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/Resources/English.lproj/Localizable.strings
error_id_to_message_t error_id_to_message[] = {
	{ "kAMDAPIInternalError", "There was an internal API error." },
	{ "kAMDAlreadyArchivedError", "The application is already archived." },
	{ "kAMDAppBlacklistedError", "This app is not allowed to be installed on this device." },
	{ "kAMDAppexBundleIDConflictWithOtherIdentifierError", "This application contains an app extension with a bundle identifier that conflicts with the bundle identifier of another app or app extension already installed." },
	{ "kAMDApplicationAlreadyInstalledError", "A system application with the given bundle identifier is already installed on the device and cannot be replaced." },
	{ "kAMDApplicationMoveFailedError", "The application could not be moved into place on the device." },
	{ "kAMDApplicationSandboxFailedError", "The application could not be sandboxed." },
	{ "kAMDApplicationVerificationFailedError", "The application could not be verified." },
	{ "kAMDArchiveDestructionFailedError", "Could not remove the application archive." },
	{ "kAMDBadHeaderError", "Could not transfer file." },
	{ "kAMDBreadcrumbFailedError", "Could not write installation breadcrumb." },
	{ "kAMDBreadcrumbUnlockError", "Could not update installation breadcrumb." },
	{ "kAMDBundleIDConflictWithOtherIdentifierError", "This application's bundle identifier conflicts with the identifier of another app or app extension already installed." },
	{ "kAMDBundleVerificationFailedError", "The carrier bundle could not be verified." },
	{ "kAMDBundleiTunesMetadataVersionMismatchError", "This application's iTunesMetadata.plist specifies versions that do not match the versions listed for the app in its Info.plist" },
	{ "kAMDBusyError", "The device is busy." },
	{ "kAMDCUPairingContinueError", "Continue pairing process over the network." },
	{ "kAMDCUPairingError", "General failure while pairing over the network." },
	{ "kAMDCUPairingResetError", "Pairing was reset due to earlier issues, try again." },
	{ "kAMDCannotTranslateError", "Could not translate messages from device" },
	{ "kAMDCarrierBundleCopyFailedError", "Could not install the carrier bundle." },
	{ "kAMDCarrierBundleDirectoryCreationFailedError", "Could not create the carrier bundle directory." },
	{ "kAMDCarrierBundleMissingSupportedSIMsError", "There are no supported SIMs for this carrier bundle." },
	{ "kAMDCheckinConnectionFailedError", "The service did not start properly on the device." },
	{ "kAMDCheckinOutOfMemoryError", "The service did not start properly on the device." },
	{ "kAMDCheckinReceiveFailedError", "The service did not start properly on the device." },
	{ "kAMDCheckinResponseFailedError", "The service did not start properly on the device." },
	{ "kAMDCheckinSendFailedError", "The service did not start properly on the device." },
	{ "kAMDCheckinSetupFailedError", "Could not start service on device" },
	{ "kAMDCheckinTimeoutError", "The service did not start properly on the device." },
	{ "kAMDCommCenterNotificationFailedError", "Could not listen for notification from the baseband." },
	{ "kAMDContainerCreationFailedError", "Could not create application container." },
	{ "kAMDContainerP0wnFailedError", "Could not repair permissions on application container." },
	{ "kAMDContainerRemovalFailedError", "Could not remove the application container." },
	{ "kAMDCryptoError", "Could not establish a secure connection to the device." },
	{ "kAMDDeviceDisconnectedError", "This device is no longer connected." },
	{ "kAMDDeviceFamilyNotSupported", "This application does not support this kind of device." },
	{ "kAMDDeviceNotSupportedByThinningError", "This application is not built for this device." },
	{ "kAMDDeviceOSVersionTooLow", "The device OS version is too low." },
	{ "kAMDDeviceRefNoGood", "This device is no longer connected." },
	{ "kAMDDeviceTooNewError", "This application needs to be updated." },
	{ "kAMDDictCreationFailedError", "Could not extract capabilities from the request." },
	{ "kAMDDigestFailedError", "Could not read disk image." },
	{ "kAMDEOFError", "End of file." },
	{ "kAMDEmbeddedProfileInstallFailedError", "Could not install the embedded provisioning profile." },
	{ "kAMDErrorError", "An error occurred." },
	{ "kAMDEscrowLockedError", "Device is not available until first unlock after boot." },
	{ "kAMDExecutableTwiddleFailedError", "Could not change executable permissions on the application." },
	{ "kAMDExistenceCheckFailedError", "Could not check to see if the application already exists." },
	{ "kAMDFMiPProtectedError", "The device is in lost mode." },
	{ "kAMDFileExistsError", "The file already exists." },
	{ "kAMDGeoJSONCaptureFailedError", "Could not save the GeoJSON data." },
	{ "kAMDGetProhibitedError", "Cannot retrieve value from the passcode locked device." },
	{ "kAMDImmutableValueError", "This value cannot be changed." },
	{ "kAMDIncorrectArchitectureError", "This application does not support this device's CPU type." },
	{ "kAMDInstallMapUpdateFailedError", "Could not update the installed applications list." },
	{ "kAMDInstallProhibitedError", "Installation of apps is prohibited by a policy on the device." },
	{ "kAMDInvalidActivationRecordError", "The activation record is not valid." },
	{ "kAMDInvalidArgumentError", "The argument is invalid." },
	{ "kAMDInvalidCheckinError", "Could not start service on device" },
	{ "kAMDInvalidDiskImageError", "The disk image is invalid." },
	{ "kAMDInvalidHostIDError", "The device does not recognize this host." },
	{ "kAMDInvalidPairRecordError", "The host is no longer paired with the device." },
	{ "kAMDInvalidResponseError", "Received an unexpected response from the device." },
	{ "kAMDInvalidSINFError", "The encryption information included with this application is not valid so this application cannot be installed on this device." },
	{ "kAMDInvalidServiceError", "The service is invalid." },
	{ "kAMDInvalidSessionIDError", "The session ID is invalid." },
	{ "kAMDInvalidSymlinkError", "The bundle contained an invalid symlink." },
	{ "kAMDInvalidiTunesMetadataPlistError", "This application's iTunesMetadata.plist is not valid." },
	{ "kAMDIsDirectoryError", "The path is a directory." },
	{ "kAMDLookupFailedError", "Could not list installed applications." },
	{ "kAMDMCChallengeRequired", "A policy on the device requires secure pairing." },
	{ "kAMDMCProtected", "Pairing is prohibited by a policy on the device." },
	{ "kAMDManifestCaptureFailedError", "Could not save the application manifest." },
	{ "kAMDMapGenerationFailedError", "Could not generate the map." },
	{ "kAMDMismatchedApplicationIdentifierEntitlementError", "This application's application-identifier entitlement does not match that of the installed application. These values must match for an upgrade to be allowed." },
	{ "kAMDMismatchedBundleIDSigningIdentifierError", "This application's bundle identifier does not match its code signing identifier." },
	{ "kAMDMissingActivationRecordError", "The activation record could not be found." },
	{ "kAMDMissingApplicationIdentifierError", "Request was missing the application identifier." },
	{ "kAMDMissingAttributeValueError", "Request was missing a required value." },
	{ "kAMDMissingBundleExecutableError", "The application bundle does not contain an executable." },
	{ "kAMDMissingBundleIdentifierError", "The application bundle does not contain a valid identifier." },
	{ "kAMDMissingBundlePathError", "Could not determine the application bundle path." },
	{ "kAMDMissingBundleVersionError", "The bundle's Info.plist does not contain a CFBundleVersion key or its value is not a string." },
	{ "kAMDMissingCommandError", "The request did not contain a command." },
	{ "kAMDMissingContainerError", "Could not find the container for the installed application." },
	{ "kAMDMissingContainerPathError", "Request was missing the container path." },
	{ "kAMDMissingDigestError", "The digest is missing." },
	{ "kAMDMissingHostIDError", "The device does not recognize this host." },
	{ "kAMDMissingImageTypeError", "The image is missing." },
	{ "kAMDMissingKeyError", "The key is missing." },
	{ "kAMDMissingOptionsError", "The options are missing." },
	{ "kAMDMissingPackagePathError", "Request was missing the package path." },
	{ "kAMDMissingPairRecordError", "The host is not paired with the device." },
	{ "kAMDMissingServiceError", "The service is missing." },
	{ "kAMDMissingSessionIDError", "The session ID is missing." },
	{ "kAMDMissingValueError", "The value is missing." },
	{ "kAMDMobileImageMounterAlreadyMounted", "Image is already mounted." },
	{ "kAMDMobileImageMounterDeviceLocked", "The device is locked." },
	{ "kAMDMobileImageMounterDigestCreationFailed", "Could not support development." },
	{ "kAMDMobileImageMounterDigestFailed", "Could not support development." },
	{ "kAMDMobileImageMounterImageInfoCreationFailed", "Could not support development." },
	{ "kAMDMobileImageMounterImageMapLoadFailed", "Could not support development." },
	{ "kAMDMobileImageMounterImageMapStoreFailed", "Could not support development." },
	{ "kAMDMobileImageMounterImageMountFailed", "Could not support development." },
	{ "kAMDMobileImageMounterImageMoveFailed", "Could not support development." },
	{ "kAMDMobileImageMounterImageVerificationFailed", "Could not support development." },
	{ "kAMDMobileImageMounterMissingImagePath", "Could not support development." },
	{ "kAMDMobileImageMounterMissingImageSignature", "Could not support development." },
	{ "kAMDMobileImageMounterMissingImageType", "Could not support development." },
	{ "kAMDMobileImageMounterMountPathMissing", "Could not support development." },
	{ "kAMDMobileImageMounterMountPathNotEmpty", "Could not support development." },
	{ "kAMDMobileImageMounterResponseCreationFailed", "Could not support development." },
	{ "kAMDMobileImageMounterTrustCacheLoadFailed", "Could not support development." },
	{ "kAMDMuxConnectError", "Could not connect to the device." },
	{ "kAMDMuxCreateListenerError", "Could not listen for USB devices." },
	{ "kAMDMuxError", "There was an error with the USB device multiplexor." },
	{ "kAMDMuxGetListenerError", "Could not get the USB listener." },
	{ "kAMDNewsstandArtworkCaptureFailedError", "Could not save the Newsstand artwork." },
	{ "kAMDNoResourcesError", "Could not allocate a resource." },
	{ "kAMDNoSpaceError", "No space is available on the device." },
	{ "kAMDNoWifiSyncSupportError", "Device doesn't support wireless sync." },
	{ "kAMDNotConnectedError", "Not connected to the device." },
	{ "kAMDNotEntitledError", "The requesting application is not allowed to make this request." },
	{ "kAMDNotFoundError", "The file could not be found." },
	{ "kAMDNotificationFailedError", "Could not post a notification." },
	{ "kAMDOverrunError", "There was a buffer overrun." },
	{ "kAMDPackageExtractionFailedError", "Could not open the application package." },
	{ "kAMDPackageInspectionFailedError", "Could not inspect the application package." },
	{ "kAMDPackageMoveFailedError", "Could not move the application package into the staging location." },
	{ "kAMDPackagePatchFailedError", "Could not apply patch update to application." },
	{ "kAMDPairingDialogResponsePendingError", "The user has not yet responded to the pairing request." },
	{ "kAMDPairingProhibitedError", "Pairing only allowed over USB." },
	{ "kAMDPasswordProtectedError", "The device is passcode protected." },
	{ "kAMDPasswordRequiredError", "A passcode is required to be set on the device." },
	{ "kAMDPathConversionFailedError", "Could not convert the path." },
	{ "kAMDPermissionError", "You do not have permission." },
	{ "kAMDPluginCopyFailedError", "Could not copy VPN Plugin into app container." },
	{ "kAMDProhibitedBySupervision", "Operation prohibited on supervised devices." },
	{ "kAMDProvisioningProfileNotValid", "The provisioning profile is not valid." },
	{ "kAMDReadError", "Could not read from the device." },
	{ "kAMDReceiveMessageError", "Could not receive a message from the device." },
	{ "kAMDRemoveProhibitedError", "Cannot remove value on device." },
	{ "kAMDRequireCUPairingBackoffError", "Retry later." },
	{ "kAMDRequireCUPairingCodeError", "Invalid PIN code entered." },
	{ "kAMDRequireCUPairingError", "Cannot pair over network yet" },
	{ "kAMDRestoreContainerFailedError", "Could not restore the application container." },
	{ "kAMDSUFirmwareError", "Could not flash the firmware." },
	{ "kAMDSUPatchError", "Could not patch the file." },
	{ "kAMDSUVerificationError", "The software update package could not be verified." },
	{ "kAMDSavePairRecordFailedError", "Could not save the pairing record." },
	{ "kAMDSeatbeltProfileRemovalFailedError", "Could not remove the application seatbelt profile." },
	{ "kAMDSendMessageError", "Could not send a message to the device." },
	{ "kAMDServiceLimitError", "Too many instances of this service are already running." },
	{ "kAMDServiceProhibitedError", "The service could not be started on the device." },
	{ "kAMDSessionActiveError", "The session is active." },
	{ "kAMDSessionInactiveError", "The session is inactive." },
	{ "kAMDSetProhibitedError", "Cannot set value on device." },
	{ "kAMDStageCreationFailedError", "Could not create the staging directory." },
	{ "kAMDStartServiceError", "The service could not be started." },
	{ "kAMDSuccess", "There was no error." },
	{ "kAMDSymlinkFailedError", "Could not create the symlink." },
	{ "kAMDTimeOutError", "The operation timed out." },
	{ "kAMDTooBigError", "The message is too big." },
	{ "kAMDUndefinedError", "An unknown error occurred." },
	{ "kAMDUninstallProhibitedError", "Uninstallation of apps is prohibited by a policy on the device." },
	{ "kAMDUnknownCommandError", "The device does not recognize the command." },
	{ "kAMDUnknownPacketError", "The packet is unknown." },
	{ "kAMDUnsupportedError", "This operation is unsupported." },
	{ "kAMDUserDeniedPairingError", "The device rejected the pairing attempt." },
	{ "kAMDWriteError", "Could not write to the device." },
	{ "kAMDWrongDroidError", "The device is in recovery mode." },
	{ "kAMDiTunesArtworkCaptureFailedError", "Could not save the iTunes artwork." },
	{ "kAMDiTunesMetadataCaptureFailedError", "Could not save the iTunes metadata." },
	{ "kMobileHouseArrestApplicationLookupFailed", "The requested application is not a user application." },
	{ "kMobileHouseArrestDictionaryFailed", "The request contained an invalid request dictionary." },
	{ "kMobileHouseArrestInstallationLookupFailed", "Could not find the requested application." },
	{ "kMobileHouseArrestInvalidPath", "The requested application contained an invalid data container path." },
	{ "kMobileHouseArrestMissingCommand", "The request was missing a command." },
	{ "kMobileHouseArrestMissingContainer", "The requested application does not contain a valid data container." },
	{ "kMobileHouseArrestMissingIdentifier", "The request was missing an application identifier." },
	{ "kMobileHouseArrestPathConversionFailed", "Could not convert the requested application's data container path." },
	{ "kMobileHouseArrestPathMissing", "The requested application's data container path does not exist." },
	{ "kMobileHouseArrestUnknownCommand", "The request contained an invalid command." },
};

const int error_id_to_message_count = sizeof(error_id_to_message) / sizeof(error_id_to_message_t);

const char* get_error_message(unsigned int error) {
	const char* id = NULL;

	// this creates an error code to match what's defined in `errorcode_to_id`;
	// taken from https://github.com/samdmarshall/SDMMobileDevice/blob/c3e1e97b1310c7a7a10f68281752760038b75e16/Framework/include/SDMMobileDevice/SDMMD_Error.h#L512
	// note that the `error & 0xff` isn't done here because there are defined errors like `0xe8008001`
	const unsigned int error_code = error | 0xe8000000;

	// Lookup error localization id
	for (int i = 0; i < errorcode_to_id_count; i++) {
		if (errorcode_to_id[i].error == error_code) {
			id = errorcode_to_id[i].id;
			break;
		}
	}

	// Lookup error message
	if (id) {
		for (int i = 0; i < error_id_to_message_count; i++)
			if (strcmp(error_id_to_message[i].id, id) == 0)
				return error_id_to_message[i].message;
	}

	// If message is not found, then at least return id if it was found, otherwise NULL
	return id;
};
